/*
 * Copyright (c) 2015. 速位中国
 */

package com.commons;

import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * Simple to Introduction
 *
 * @Description: 字节数组和基本类型间的互相转换
 * @author: zhaojianji
 * @CreateDate: 2015/5/14
 * @version: v1.0
 */
public class TypeConvert {



    /* byte转short */
    public static short getShort(byte[] buf, boolean asc) {
        short r = 0;
        int len = buf.length;
        if (asc)
            for (int i = len - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x00ff);
            }
        else
            for (int i = 0; i < len; i++) {
                r <<= 8;
                r |= (buf[i] & 0x00ff);
            }

        return r;
    }

    /* B2 -> 0xB2 */
    public static int stringToByte(String in, byte[] b) throws Exception {
        if (b.length < in.length() / 2) {
            throw new Exception("byte array too small");
        }

        int j = 0;
        StringBuilder buf = new StringBuilder(2);
        for (int i = 0; i < in.length(); i++, j++) {
            buf.insert(0, in.charAt(i));
            buf.insert(1, in.charAt(i + 1));
            int t = Integer.parseInt(buf.toString(), 16);
            System.out.println("byte hex value:" + t);
            b[j] = (byte) t;
            i++;
            buf.delete(0, 2);
        }

        return j;
    }

    /* byte to  int */
    public static int getInt(byte[] buf, boolean asc, int len) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (len > 4) {
            throw new IllegalArgumentException("byte array size > 4 !");
        }
        int r = 0;
        if (asc)
            for (int i = len - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x000000ff);
            }
        else
            for (int i = 0; i < len; i++) {
                r <<= 8;
                r |= (buf[i] & 0x000000ff);
            }
        return r;
    }

    /* int -> byte[] */
    public static byte[] intToBytes(int num) {
        byte[] b = new byte[4];
        for (int i = 0; i < 4; i++) {
            b[i] = (byte) (num >>> (24 - i * 8));
        }

        return b;
    }

    /* short to byte[] */
    public static byte[] shortToBytes(short num) {
        byte[] b = new byte[2];

        for (int i = 0; i < 2; i++) {
            b[i] = (byte) (num >>> (i * 8));
        }

        return b;
    }

    /* byte to String */
    private static char findHex(byte b) {
        int t = new Byte(b).intValue();
        t = t < 0 ? t + 16 : t;

        if ((0 <= t) && (t <= 9)) {
            return (char) (t + '0');
        }

        return (char) (t - 10 + 'A');
    }

    public static String byteToString(byte b) {
        byte high, low;
        byte maskHigh = (byte) 0xf0;
        byte maskLow = 0x0f;

        high = (byte) ((b & maskHigh) >> 4);
        low = (byte) (b & maskLow);

        return String.valueOf(findHex(high)) +
                findHex(low);
    }

    /* short -> byte */
    public static byte[] getBytes(short s, boolean asc) {
        byte[] buf = new byte[2];
        if (asc) for (int i = buf.length - 1; i >= 0; i--) {
            buf[i] = (byte) (s & 0x00ff);
            s >>= 8;
        }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x00ff);
                s >>= 8;
            }
        return buf;
    }

    /* int -> byte[] */
    public static byte[] getBytes(int s, boolean asc) {
        byte[] buf = new byte[4];
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = (byte) (s & 0x000000ff);
                s >>= 8;
            }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x000000ff);
                s >>= 8;
            }
        return buf;
    }

    /* long -> byte[] */
    public static byte[] getBytes(long s, boolean asc) {
        byte[] buf = new byte[8];
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                buf[i] = (byte) (s & 0x00000000000000ff);
                s >>= 8;
            }
        else
            for (int i = 0; i < buf.length; i++) {
                buf[i] = (byte) (s & 0x00000000000000ff);
                s >>= 8;
            }
        return buf;
    }

    /* byte[]->int */
    public static int getInt(byte[] buf, boolean asc) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (buf.length > 4) {
            throw new IllegalArgumentException("byte array size > 4 !");
        }
        int r = 0;
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x000000ff);
            }
        else
            for (byte aBuf : buf) {
                r <<= 8;
                r |= (aBuf & 0x000000ff);
            }
        return r;
    }

    /* byte[] -> long */
    public static long getLong(byte[] buf, boolean asc) {
        if (buf == null) {
            throw new IllegalArgumentException("byte array is null!");
        }
        if (buf.length > 8) {
            throw new IllegalArgumentException("byte array size > 8 !");
        }
        long r = 0;
        if (asc)
            for (int i = buf.length - 1; i >= 0; i--) {
                r <<= 8;
                r |= (buf[i] & 0x00000000000000ff);
            }
        else
            for (byte aBuf : buf) {
                r <<= 8;
                r |= (aBuf & 0x00000000000000ff);
            }
        return r;
    }

    /**
     * byte数组转换为无符号short整数
     *
     * @param bytes
     *            byte数组
     * @return short整数
     */
    public static int byte2ToUnsignedShort(byte[] bytes) {
        return byte2ToUnsignedShort(bytes, 0);
    }

    /**
     * byte数组转换为无符号short整数
     *
     * @param bytes
     *            byte数组
     * @param off
     *            开始位置
     * @return short整数
     */
    public static int byte2ToUnsignedShort(byte[] bytes, int off) {
        int high = bytes[off];
        int low = bytes[off + 1];
        return (high << 8 & 0xFF00) | (low & 0xFF);
    }

    /**
     * 从指定数组的指定索引处查找指定结束符,
     * 并将指定的开始索引(包括)到指定结束符索引(不包括)间的字节数组以字符串形式返回
     * 该方法重载,默认只需指定数组和开始索引,结束符默认0x00,字符集默认utf-8
     * @param data
     * @param startIndex
     * @return
     */
    public static String getStringFromBytesWithTailed(byte[] data,int startIndex,int index){
        byte tailed = 0x00;
        if(index <= 0){
            index = 1;
        }
        return getStringFromBytesWithTailed(data,startIndex,index,tailed);
    }

    /**
     * @
     * @param data
     * @param startIndex
     * @param tailed
     * @return
     */
    public static String getStringFromBytesWithTailed(byte[] data,int startIndex,int index,byte tailed){
        return getStringFromBytesWithTailed(data,startIndex,index,tailed,null);
    }

    public static String getStringFromBytesWithTailed(byte[] data,int startIndex,int index,byte tailed,String charset){
        if(charset == null){
            charset = "UTF-8";
        }
        int end = data.length;
        int findCount = 0;
        if(startIndex >= 0 && startIndex < end){
            for (int i = startIndex; i < data.length; i++) {
                if (data[i] == tailed) {
                    findCount++;
                    if(findCount == index){
                        end = i;
                        break;
                    }else{
                        startIndex = i + 1;
                        if(index > 1){
                            index--;
                            return getStringFromBytesWithTailed(data,startIndex,index,tailed,charset);
                        }else{
                            return null;
                        }

                    }

                }
            }
            return new String(Arrays.copyOfRange(data, tailed, end), Charset.forName("UTF-8"));
        }else{
            return null;
        }

    }
}


